package com.ctshk.rpc.order.tour.service.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ctshk.common.enums.*;
import com.ctshk.common.utils.DateUtil;
import com.ctshk.rpc.finance.json.AccountJson;
import com.ctshk.rpc.finance.req.bill.BillAddRefundReq;
import com.ctshk.rpc.finance.req.bill.BillOperateRefundReq;
import com.ctshk.rpc.finance.service.IFinanceBillService;
import com.ctshk.rpc.order.tour.dto.custom.ApprovalQuitInfoDTO;
import com.ctshk.rpc.order.tour.req.*;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.tour.req.schedule.UpdateScheduleNumReq;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.BConst;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.rpc.insurance.req.tp.CancelReq;
import com.ctshk.rpc.insurance.service.IInsuranceService;
import com.ctshk.rpc.iotc.req.OperateBankRefundReq;
import com.ctshk.rpc.iotc.req.OperatePromotionRefundReq;
import com.ctshk.rpc.iotc.service.IOperateBankPreferenceService;
import com.ctshk.rpc.iotc.service.IOperatePromotionService;
import com.ctshk.rpc.order.tour.code.CollectionRefundWayIdCode;
import com.ctshk.rpc.order.tour.code.CurrencyIdCode;
import com.ctshk.rpc.order.tour.code.DeductionAmountType;
import com.ctshk.rpc.order.tour.code.DeductionRefundType;
import com.ctshk.rpc.order.tour.code.ISCode;
import com.ctshk.rpc.order.tour.code.IsDeletedCode;
import com.ctshk.rpc.order.tour.code.QueryType;
import com.ctshk.rpc.order.tour.code.RefundStatusCode;
import com.ctshk.rpc.order.tour.code.ScheduleStatusCode;
import com.ctshk.rpc.order.tour.code.SeriesOrderErrorCode;
import com.ctshk.rpc.order.tour.code.SeriesOrderTouristQuitRefundStatusCode;
import com.ctshk.rpc.order.tour.constant.Constants;
import com.ctshk.rpc.order.tour.dto.SeriesOrderReceiptDetailsGetInsuranceDTO;
import com.ctshk.rpc.order.tour.dto.SeriesOrderReceiptDetailsPreviewInsuranceDTO;
import com.ctshk.rpc.order.tour.dto.SeriesOrderReceiptDetailsPreviewInsuranceItemDTO;
import com.ctshk.rpc.order.tour.dto.SeriesOrderTouristQuitAddCalculationDTO;
import com.ctshk.rpc.order.tour.dto.SeriesOrderTouristQuitListDTO;
import com.ctshk.rpc.order.tour.entity.SeriesOrder;
import com.ctshk.rpc.order.tour.entity.SeriesOrderAmountStatistics;
import com.ctshk.rpc.order.tour.entity.SeriesOrderCollection;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristInfo;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristQuit;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristQuitNotice;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderAmountStatisticsMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderCollectionMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderReceiptDetailsMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristInfoMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristQuitMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristQuitNoticeMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristVisaMapper;
import com.ctshk.rpc.order.tour.service.ISeriesOrderCollectionService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderReceiptDetailsService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderTouristOtherFeeService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderTouristQuitService;
import com.ctshk.rpc.order.tour.util.PacificUtil;
import com.ctshk.rpc.order.tour.util.Utils;
import com.ctshk.rpc.order.tour.vo.RelationInfoJsonBankPreference;
import com.ctshk.rpc.order.tour.vo.RelationInfoJsonDiscount;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.dto.member.CrmAccountDTO;
import com.ctshk.rpc.system.dto.mian.data.MainDataDeductionRulesDTO;
import com.ctshk.rpc.system.dto.mian.data.MainDataDeductionRulesDetailsDTO;
import com.ctshk.rpc.system.dto.mian.data.MainDataNotGroupRulesDTO;
import com.ctshk.rpc.system.dto.mian.data.MainDataNotGroupRulesDetailsDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.req.crm.member.CrmMemberQueryReq;
import com.ctshk.rpc.system.req.main.data.MainDataDeductionRulesIdReq;
import com.ctshk.rpc.system.req.main.data.MainDataNotGroupRulesIdReq;
import com.ctshk.rpc.system.service.ICrmMemberService;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.IMainDataDeductionRulesService;
import com.ctshk.rpc.system.service.IMainDataNotGroupRulesService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.tour.dto.schedule.SeriesTripScheduleDTO;
import com.ctshk.rpc.tour.dto.schedule.SeriesTripScheduleDataDTO;
import com.ctshk.rpc.tour.dto.schedule.SeriesTripScheduleTeamRuleDTO;
import com.ctshk.rpc.tour.service.ISeriesTripScheduleService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;

/**
 * <p>
 * 系列团游客退团 服务实现类
 * </p>
 *
 * @author 谭响
 * @since 2021-01-29
 */
@DubboService
public class SeriesOrderTouristQuitServiceImpl extends ServiceImpl<SeriesOrderTouristQuitMapper, SeriesOrderTouristQuit> implements ISeriesOrderTouristQuitService {

    @Autowired
    private SeriesOrderTouristQuitMapper seriesOrderTouristQuitMapper;

    @Autowired
    private SeriesOrderTouristInfoMapper seriesOrderTouristInfoMapper;

    @Autowired
    private SeriesOrderAmountStatisticsMapper seriesOrderAmountStatisticsMapper;

    @Autowired
    private SeriesOrderMapper seriesOrderMapper;

    @Autowired
    private SeriesOrderTouristQuitNoticeMapper seriesOrderTouristQuitNoticeMapper;

    @DubboReference
    private ISeriesTripScheduleService iSeriesTripScheduleService;

    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private IMainDataDeductionRulesService iMainDataDeductionRulesService;

    @DubboReference
    private IMainDataNotGroupRulesService iMainDataNotGroupRulesService;

    @DubboReference
    private IMainDataCurrencyService iMainDataCurrencyService;

    @Autowired
    private SeriesOrderCollectionMapper seriesOrderCollectionMapper;

    @DubboReference
    private IOperatePromotionService iOperatePromotionService;

    @DubboReference
    private IOperateBankPreferenceService iOperateBankPreferenceService;

    @DubboReference
    private IInsuranceService iInsuranceService;

    @Autowired
    private ISeriesOrderCollectionService iSeriesOrderCollectionService;

    @Autowired
    private ISeriesOrderReceiptDetailsService iSeriesOrderReceiptDetailsService;

    @Autowired
    private SeriesOrderReceiptDetailsMapper seriesOrderReceiptDetailsMapper;

    @DubboReference
    private ICrmMemberService iCrmMemberService;

    @DubboReference
    private ISysApprovalService iSysApprovalService;

    @DubboReference
    private ISeriesOrderService iSeriesOrderService;

    @Autowired
    SeriesOrderTouristVisaMapper seriesOrderTouristVisaMapper;
    
    @Autowired
    ISeriesOrderTouristOtherFeeService iSeriesOrderTouristOtherFeeService;

    @DubboReference
    private IFinanceBillService financeBillService;


    
    /**
     * 列表
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageResponse<SeriesOrderTouristQuitListDTO> list(SeriesOrderTouristQuitListReq req) {
        IPage<SeriesOrderTouristInfo> iPage = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id",req.getOrderId());
        queryWrapper.eq("is_deleted",0);
        queryWrapper.eq("is_full_info",1);
        queryWrapper.like(StringUtils.isNotBlank(req.getCondition1()),"cn_fullname",req.getCondition1());
        queryWrapper.or();
        queryWrapper.like(StringUtils.isNotBlank(req.getCondition1()),"en_fullname",req.getCondition1());
        IPage<SeriesOrderTouristInfo> page = seriesOrderTouristInfoMapper.selectPage(iPage, queryWrapper);
        List<SeriesOrderTouristQuitListDTO> list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())){
            for (SeriesOrderTouristInfo touristInfo : page.getRecords()) {
                SeriesOrderTouristQuitListDTO dto = EntityUtil.copy(touristInfo,SeriesOrderTouristQuitListDTO.class);
                dto.setTouristId(touristInfo.getId());
                QueryWrapper<SeriesOrderTouristQuit> quitQueryWrapper = new QueryWrapper<>();
                quitQueryWrapper.eq("tourist_id",touristInfo.getId());
                quitQueryWrapper.eq("is_deleted",0);
                quitQueryWrapper.eq(req.getRefundStatus() != null,"refund_status",req.getRefundStatus());
                SeriesOrderTouristQuit quit = seriesOrderTouristQuitMapper.selectOne(quitQueryWrapper);
                if (quit != null){
                    dto = EntityUtil.copy(quit,SeriesOrderTouristQuitListDTO.class);
                    if (quit.getCreateId() != null){
                        UserDTO userDTO = iSysUserService.queryCacheUser(quit.getCreateId());
                        if (userDTO != null){
                            dto.setCreateName(userDTO.getFullName());
                            dto.setCreateDept(userDTO.getDept());
                        }
                    }
                }
                list.add(dto);
            }
        }
        /*IPage<SeriesOrderTouristQuitListDTO> pageParam = new Page<>(req.getPageNo(), req.getPageSize());
     //   IPage<SeriesOrderTouristQuitListDTO> pageResult = seriesOrderTouristQuitMapper.selectListBySelective(pageParam, req);
        IPage<SeriesOrderTouristQuitListDTO> pageResult = seriesOrderTouristQuitMapper.queryQuitList(req,pageParam);
        for (SeriesOrderTouristQuitListDTO record : pageResult.getRecords()) {
            if(record.getCreateId() == null) {
                continue;
            }
            UserDTO userDTO = iSysUserService.queryCacheUser(record.getCreateId());
            if (userDTO != null){
                record.setCreateName(userDTO.getFullName());
                record.setCreateDept(userDTO.getDept());
            }
        }*/
        PageResponse<SeriesOrderTouristQuitListDTO> pageResponse = new PageResponse<>(list,
                page.getCurrent() == 1,
                page.getTotal() <= (page.getCurrent() * page.getSize()),
                page.getTotal(), page.getCurrent(),
                page.getSize());
        return pageResponse;
    }

    /**
     * 添加
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result add(SeriesOrderTouristQuitAddReq req) {
        //游客统计
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getId, req.getTouristId());
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        SeriesOrderTouristInfo touristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper);
        if (touristInfo == null) {
            return Result.failed(SystemError.SYS_411);
        }
        //是否有申请退团记录
        QueryWrapper<SeriesOrderTouristQuit> quitQueryWrapper = new QueryWrapper<>();
        quitQueryWrapper.eq("tourist_id",touristInfo.getId());
        quitQueryWrapper.ne("refund_status",4);
        quitQueryWrapper.eq("is_deleted",0);
        SeriesOrderTouristQuit quit = seriesOrderTouristQuitMapper.selectOne(quitQueryWrapper);
        if (quit != null){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4053);
        }
        //订单统计
        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderAmountStatistics::getOrderId, req.getOrderId());
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper2);

        if (statistics == null) {
            return Result.failed(SystemError.SYS_411);
        }

        //退款金额 港幣金額=其他貨幣金額×對應的門市匯率
        BigDecimal quitRefundAmount = null;
        if(Objects.equals(CurrencyIdCode.HKD.getCode(), req.getCurrencyTypeId())) {
            quitRefundAmount = req.getCurrencyRefundAmount();
        } else {
            quitRefundAmount = req.getCurrencyRefundAmount().multiply(req.getExchangeRate());
        }

        if((quitRefundAmount.add(req.getDeductionAmount())).compareTo(touristInfo.getTotalPaidIn()) > 0) {
            return Result.failed(SeriesOrderErrorCode.QUIT_ADD_AMOUNT_LIMIT);
        }

        //查询优惠金额
        BigDecimal discountAmount = new BigDecimal(0);
        QueryWrapper<SeriesOrderCollection> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.lambda().eq(SeriesOrderCollection::getOrderId, req.getOrderId());
        queryWrapper3.lambda().eq(SeriesOrderCollection::getTouristId, req.getTouristId());
        queryWrapper3.lambda().and(object -> object.eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.BANK_PREFERENCE.getCode())
//                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.POINTS.getCode())
                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.OPERATE_PROMOTION.getCode()));
        queryWrapper3.lambda().eq(SeriesOrderCollection::getIsDeleted, IsDeletedCode.NO.getCode());
        List<SeriesOrderCollection> collectionList = seriesOrderCollectionMapper.selectList(queryWrapper3);
        for (SeriesOrderCollection collection : collectionList) {
            discountAmount = discountAmount.add(collection.getPaidInAmount());
        }

        SeriesOrderTouristQuit saveObject = EntityUtil.copy(req, SeriesOrderTouristQuit.class);
        //退团单号
        String refundNumber = getQuitNumber(req.getUserId());
        saveObject.setRefundNumber(refundNumber);
        saveObject.setRefundStatus(RefundStatusCode.APPROVAL.getCode());
        LocalDateTime now = LocalDateTime.now();
        saveObject.setId(IdWorker.getId());
        saveObject.setGmtCreate(now);
        saveObject.setGmtModified(now);
        saveObject.setCreateId(req.getUserId());
        saveObject.setModifiedId(req.getUserId());
        saveObject.setIsDeleted(IsDeletedCode.NO.getCode());
        saveObject.setRefundAmount(quitRefundAmount);
        saveObject.setDiscountAmount(discountAmount);
        saveObject.setPaidInAmount(touristInfo.getTotalPaidIn());

        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", saveObject.getId());
        Result<ApprovalStartDTO> approvalResult = iSysApprovalService.start(SystemBusinessType.OUTBOUND_TRAVEL.getCode(),
                SysApprovalType.LEAVE_OUTTRA.getCode(), req.getOrderId(),
                req.getUserId(), null, JSON.toJSONString(extendParams));
        if (!approvalResult.isSuccess()) {
            throw new BusinessException(SystemError.SYS_500);
        }
        saveObject.setApprovalId(approvalResult.getData().getApprovalId());
        boolean save = save(saveObject);
        if (!save){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(saveObject.getId());
    }

    /**
     * 添加计算
     */
    public Result<SeriesOrderTouristQuitAddCalculationDTO> addCalculation(SeriesOrderTouristQuitAddCalculationReq req) {
        //获取团期
        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(req.getScheduleId());
        if (tripScheduleDTO == null) {
            return Result.failed(SystemError.SYS_411);
        }
        SeriesTripScheduleTeamRuleDTO seriesTripScheduleTeamRuleDTO = tripScheduleDTO.getSeriesTripScheduleTeamRuleDTO();

        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderAmountStatistics::getOrderId, req.getOrderId());
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper);
        if (statistics == null) {
            return Result.failed(SystemError.SYS_411);
        }

        SeriesOrderTouristQuitAddCalculationDTO dto = EntityUtil.copy(req, SeriesOrderTouristQuitAddCalculationDTO.class);
        //当前距离出发日期多少天
        long remainDay = LocalDate.now().until(tripScheduleDTO.getDepartureDate(), ChronoUnit.DAYS);
        dto.setRemainDay(remainDay);

        //实收金额
        BigDecimal totalPaidIn = statistics.getTotalPaidIn();

        //退款金额
        BigDecimal refundAmount = new BigDecimal(0);
        //查询优惠金额
        BigDecimal discountAmount = new BigDecimal(0);
        QueryWrapper<SeriesOrderCollection> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderCollection::getOrderId, req.getOrderId());
        queryWrapper2.lambda().eq(SeriesOrderCollection::getTouristId, req.getTouristId());
        queryWrapper2.lambda().and(object -> object.eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.BANK_PREFERENCE.getCode())
//                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.POINTS.getCode())
                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.OPERATE_PROMOTION.getCode()));
        queryWrapper2.lambda().eq(SeriesOrderCollection::getIsDeleted, IsDeletedCode.NO.getCode());
        List<SeriesOrderCollection> collectionList = seriesOrderCollectionMapper.selectList(queryWrapper2);
        for (SeriesOrderCollection collection : collectionList) {
            discountAmount = discountAmount.add(collection.getPaidInAmount());
        }

        //扣款金额
        BigDecimal deductionAmount = new BigDecimal(0);

        MainDataNotGroupRulesDTO notGroupRules = null;
        MainDataDeductionRulesDTO rulesDTO = null;

        //不成团
        if (Objects.equals(tripScheduleDTO.getScheduleStatus(), ScheduleStatusCode.NO.getCode())) {
            if (seriesTripScheduleTeamRuleDTO.getNotGroupRulesId() == null) {
                return Result.failed(SeriesOrderErrorCode.NOT_QUIT_RULE_ERROR);
            }
            MainDataNotGroupRulesIdReq mainDataNotGroupRulesIdReq = new MainDataNotGroupRulesIdReq();
            mainDataNotGroupRulesIdReq.setId(seriesTripScheduleTeamRuleDTO.getNotGroupRulesId());
            notGroupRules = iMainDataNotGroupRulesService.query(mainDataNotGroupRulesIdReq);
            if (notGroupRules != null && notGroupRules.getRulesDetailsList() != null && notGroupRules.getRulesDetailsList().size() > 0) {
                //总签证费用
                BigDecimal allVisaAmount = BigDecimal.ZERO;
                //可退签证
                if (BConst.ONE.equals(notGroupRules.getIsRetreatVisa())) {
                    allVisaAmount = seriesOrderTouristVisaMapper.findAllVisaAmountByTouristId(req.getTouristId());
                }

                for (int i = notGroupRules.getRulesDetailsList().size(); i > 0; i--) {
                    MainDataNotGroupRulesDetailsDTO detailsDTO = notGroupRules.getRulesDetailsList().get(i - 1);
                    if (remainDay > detailsDTO.getBeforeDepartureDays()) {
                        if (Objects.equals(detailsDTO.getDeductionRefundType(), DeductionRefundType.FULL.getCode())) {
                            //不成团：全部退公式：扣款金額=（實收金額-優惠金額-簽證金額）
                            deductionAmount = statistics.getTotalPaidIn().subtract(detailsDTO.getDeductionAmount()).subtract(allVisaAmount);
                        } else if (Objects.equals(detailsDTO.getDeductionRefundType(), DeductionRefundType.PART.getCode())) {
                            if (Objects.equals(detailsDTO.getDeductionAmountType(), DeductionAmountType.VALUE.getCode())) {
                                //不成团：固定退 固定值公式：扣款金額=扣費金額；
                                deductionAmount = detailsDTO.getDeductionAmount();
                            } else if (Objects.equals(detailsDTO.getDeductionAmountType(), DeductionAmountType.RATIO.getCode())) {
                                //不成团：部分退 百分比公式：（實收金額-優惠金額-簽證金額）×扣款百分比；
                                MathContext context = new MathContext(2, RoundingMode.HALF_DOWN);
                                BigDecimal deductionRatio = detailsDTO.getDeductionAmount().divide(new BigDecimal(100), context);
                                deductionAmount = statistics.getTotalPaidIn().subtract(discountAmount).subtract(allVisaAmount).multiply(deductionRatio);
                            }
                        }
                        dto.setDeductionAmountType(detailsDTO.getDeductionAmountType());
                        dto.setDeductionRefundType(detailsDTO.getDeductionRefundType());
                        dto.setDeductionValue(detailsDTO.getDeductionAmount());
                        break;
                    }
                }
            }

        } else {
            if (seriesTripScheduleTeamRuleDTO.getDeductionRulesId() != null) {
                MainDataDeductionRulesIdReq mainDataDeductionRulesIdReq = new MainDataDeductionRulesIdReq();
                mainDataDeductionRulesIdReq.setId(seriesTripScheduleTeamRuleDTO.getDeductionRulesId());
                rulesDTO = iMainDataDeductionRulesService.query(mainDataDeductionRulesIdReq);
                if (rulesDTO != null && rulesDTO.getRulesDetailsDTOList() != null || rulesDTO.getRulesDetailsDTOList().size() > 0) {
                    for (int i = rulesDTO.getRulesDetailsDTOList().size(); i > 0; i--) {
                        MainDataDeductionRulesDetailsDTO detailsDTO = rulesDTO.getRulesDetailsDTOList().get(i - 1);
                        if (remainDay > detailsDTO.getBeforeDepartureDays()) {
                            if (Objects.equals(detailsDTO.getDeductionRefundType(), DeductionRefundType.FULL.getCode())) {
                                deductionAmount = statistics.getTotalPaidIn().subtract(detailsDTO.getDeductionAmount());
                            } else if (Objects.equals(detailsDTO.getDeductionRefundType(), DeductionRefundType.PART.getCode())) {
                                if (Objects.equals(detailsDTO.getDeductionAmountType(), DeductionAmountType.VALUE.getCode())) {
                                    deductionAmount = detailsDTO.getDeductionAmount();
                                } else if (Objects.equals(detailsDTO.getDeductionAmountType(), DeductionAmountType.RATIO.getCode())) {
                                    MathContext context = new MathContext(2, RoundingMode.HALF_DOWN);
                                    BigDecimal deductionRatio = detailsDTO.getDeductionAmount().divide(new BigDecimal(100), context);
                                    deductionAmount = statistics.getTotalPaidIn().subtract(discountAmount).multiply(deductionRatio);
                                }
                            }
                            dto.setDeductionAmountType(detailsDTO.getDeductionAmountType());
                            dto.setDeductionRefundType(detailsDTO.getDeductionRefundType());
                            dto.setDeductionValue(detailsDTO.getDeductionAmount());
                            break;
                        }
                    }
                }
            }
        }

        if(req.getDeductionAmount() != null) {
            deductionAmount = req.getDeductionAmount();
        }

        refundAmount = statistics.getTotalPaidIn().subtract(deductionAmount);

        dto.setDeductionAmount(deductionAmount);
        dto.setCurrencyRefundAmount(refundAmount);
        dto.setDiscountAmount(discountAmount);
        dto.setTotalPaidIn(totalPaidIn);

        if (req.getCurrencyTypeId() == null || Objects.equals(CurrencyIdCode.HKD.getCode(), req.getCurrencyTypeId())) {
            MainDataCurrencyUpdateStatusReq currencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
            currencyUpdateStatusReq.setId(CurrencyIdCode.HKD.getCode());
            Result<MainDataCurrencyQueryDTO> currencyQueryDTOResult = iMainDataCurrencyService.query(currencyUpdateStatusReq);
            if (currencyQueryDTOResult.isSuccess() && currencyQueryDTOResult.getData() != null) {
                MainDataCurrencyQueryDTO currencyQueryDTO = currencyQueryDTOResult.getData();
                dto.setCurrencyCode(currencyQueryDTO.getCurrencyCode());
                dto.setCurrencyType(currencyQueryDTO.getCurrencyName());
                dto.setCurrencyTypeId(CurrencyIdCode.HKD.getCode());
                dto.setExchangeRate(currencyQueryDTO.getMarketExchangeRate());
                dto.setCurrencyRefundAmount(refundAmount);
            }
        } else {
            MainDataCurrencyUpdateStatusReq currencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
            currencyUpdateStatusReq.setId(req.getCurrencyTypeId());
            Result<MainDataCurrencyQueryDTO> currencyQueryDTOResult = iMainDataCurrencyService.query(currencyUpdateStatusReq);
            if (currencyQueryDTOResult.isSuccess() && currencyQueryDTOResult.getData() != null) {
                MainDataCurrencyQueryDTO currencyQueryDTO = currencyQueryDTOResult.getData();
                dto.setCurrencyCode(currencyQueryDTO.getCurrencyCode());
                dto.setCurrencyType(currencyQueryDTO.getCurrencyName());
                dto.setCurrencyTypeId(CurrencyIdCode.HKD.getCode());
                dto.setExchangeRate(currencyQueryDTO.getMarketExchangeRate());
                //其他貨幣金額=港幣金額÷對應的門市匯率
                MathContext context = new MathContext(2, RoundingMode.HALF_DOWN);
                dto.setCurrencyRefundAmount(refundAmount.divide(currencyQueryDTO.getMarketExchangeRate(), context));
            }
        }
        dto.setTotalAmount(refundAmount);
        return Result.success(dto);
    }

    /**
     * 确认
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result confirm(SeriesOrderTouristQuitConfirmReq req, TokenUser currentUser) {
        SeriesOrderTouristQuit dbQuit = getById(req.getId());
        if (dbQuit == null || Objects.equals(dbQuit.getIsDeleted(),1)) {
            return Result.failed(SystemError.SYS_411);
        }
        if (!Objects.equals(dbQuit.getRefundStatus(),3)){
            throw new BusinessException(SystemError.TOUR_ORDER_30024);
        }
        SeriesOrder dbOrder = seriesOrderMapper.selectById(dbQuit.getOrderId());
        if (dbOrder == null || Objects.equals(dbOrder.getIsDeleted(),1)) {
            return Result.failed(SystemError.SYS_411);
        }

        //游客统计
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getId, req.getTouristId());
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        SeriesOrderTouristInfo touristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper);
        if (touristInfo == null) {
            return Result.failed(SystemError.SYS_411);
        }

        //订单统计
        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderAmountStatistics::getOrderId, req.getOrderId());
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper2);
        if (statistics == null) {
            return Result.failed(SystemError.SYS_411);
        }

        //团费
        BigDecimal orderGroupFee = statistics.getTotalTourFee();
        //应收
        BigDecimal orderTotalReceivables = statistics.getTotalReceivables();
        //实收
        BigDecimal orderTotalPaidIn = statistics.getTotalPaidIn();
        //已退款
        BigDecimal orderRefundAmount = statistics.getRefundAmount();
        //代收费用
        BigDecimal orderCollectionFee = statistics.getCollectionFee();
        //调整费用
        BigDecimal orderAdjustmentCost = statistics.getAdjustmentCost();
        //其他金额
        BigDecimal orderOtherAmount = statistics.getOtherAmount();
        //已出单据金额
        BigDecimal orderReceiptedAmount = statistics.getReceiptedAmount();
        //未收
        BigDecimal orderRemainingReceivables = statistics.getRemainingReceivables();


        //团费
        BigDecimal groupFee = touristInfo.getGroupFee();
        //应收
        BigDecimal totalReceivables = touristInfo.getTotalReceivables();
        //实收
        BigDecimal totalPaidIn = touristInfo.getTotalPaidIn();
        //已退款
        BigDecimal refundAmount = touristInfo.getRefundAmount();
        //代收费用
        BigDecimal collectionFee = touristInfo.getCollectionFee();
        //调整费用
        BigDecimal adjustmentCost = touristInfo.getAdjustmentCost();
        //其他金额
        BigDecimal otherAmount = touristInfo.getOtherAmount();
        //已出单据金额
        BigDecimal receiptedAmount = touristInfo.getReceiptedAmount();
        //未收
        BigDecimal remainingReceivables = touristInfo.getRemainingReceivables();


        //扣减
        totalPaidIn = totalPaidIn.subtract(dbQuit.getRefundAmount());


        //团费
        //orderGroupFee = orderGroupFee;
        //应收
        totalReceivables = totalReceivables.subtract(dbQuit.getRefundAmount());
        //实收
        totalPaidIn = totalPaidIn.subtract(dbQuit.getRefundAmount());
        //已退款
        refundAmount = refundAmount.add(dbQuit.getRefundAmount());
        //代收费用
        //collectionFee = collectionFee;
        //调整费用
        //adjustmentCost = adjustmentCost;
        //其他金额
        otherAmount = otherAmount.subtract(dbQuit.getRefundAmount());
        //已出单据金额
        //receiptedAmount = receiptedAmount;
        //未收
        remainingReceivables = remainingReceivables.subtract(dbQuit.getRefundAmount());


        //团费
        //orderGroupFee = orderGroupFee;
        //应收
        orderTotalReceivables = orderTotalReceivables.subtract(totalReceivables);
        //实收
        orderTotalPaidIn = orderTotalPaidIn.subtract(totalPaidIn);
        //已退款
        orderRefundAmount = orderRefundAmount.add(refundAmount);
        //代收费用
        //orderCollectionFee = orderCollectionFee;
        //调整费用
        //orderAdjustmentCost = orderAdjustmentCost;
        //其他金额
        orderOtherAmount = orderOtherAmount.subtract(otherAmount);
        //已出单据金额
        //orderReceiptedAmount = orderReceiptedAmount;
        //未收
        orderRemainingReceivables = orderRemainingReceivables.subtract(remainingReceivables);

        //游客统计
        touristInfo.setGroupFee(groupFee);
        touristInfo.setTotalReceivables(totalReceivables);
        touristInfo.setTotalPaidIn(totalPaidIn);
        touristInfo.setRefundAmount(refundAmount);
        touristInfo.setCollectionFee(collectionFee);
        touristInfo.setAdjustmentCost(adjustmentCost);
        touristInfo.setOtherAmount(otherAmount);
        touristInfo.setReceiptedAmount(receiptedAmount);
        touristInfo.setRemainingReceivables(remainingReceivables);
        touristInfo.setBuyInsurance(ISCode.NO.getCode());
        int updateTourist = seriesOrderTouristInfoMapper.updateById(touristInfo);
        //订单统计
        statistics.setTotalTourFee(orderGroupFee);
        statistics.setTotalReceivables(orderTotalReceivables);
        statistics.setTotalPaidIn(orderTotalPaidIn);
        statistics.setRefundAmount(orderRefundAmount);
        statistics.setCollectionFee(orderCollectionFee);
        statistics.setAdjustmentCost(orderAdjustmentCost);
        statistics.setOtherAmount(orderOtherAmount);
        statistics.setReceiptedAmount(orderReceiptedAmount);
        statistics.setRemainingReceivables(orderRemainingReceivables);
        int updateStatics = seriesOrderAmountStatisticsMapper.updateById(statistics);
        SeriesOrderTouristQuit updateObject = EntityUtil.copy(req, SeriesOrderTouristQuit.class);
        updateObject.setRefundStatus(SeriesOrderTouristQuitRefundStatusCode.ALREADY.getCode());
        boolean updateQuit = updateById(updateObject);
        //旅客其他费用更新
        SeriesOrderTouristOtherFeeSaveRefundReq otherFeeSaveRefundReq = new SeriesOrderTouristOtherFeeSaveRefundReq();
        otherFeeSaveRefundReq.setTouristId(touristInfo.getId());
        otherFeeSaveRefundReq.setAmount(touristInfo.getRefundAmount());
        otherFeeSaveRefundReq.setOrderId(touristInfo.getOrderId());
        otherFeeSaveRefundReq.setRelationId(updateObject.getId());
        boolean saveRefund = iSeriesOrderTouristOtherFeeService.saveRefund(otherFeeSaveRefundReq, currentUser);
        if (updateTourist <= 0 || updateStatics <= 0 || !updateQuit || !saveRefund){
            throw new BusinessException(SystemError.SYS_437);
        }
        //退团通知书
        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(req.getScheduleId());
        SeriesTripScheduleDataDTO seriesTripScheduleDataDTO = tripScheduleDTO.getSeriesTripScheduleDataDTO();
        List<SeriesOrderTouristQuitNoticeAddQuitItemReq> noticeAddQuitItemReqList = new ArrayList<>();
        SeriesOrderTouristQuitNoticeAddQuitItemReq noticeAddQuitItemReq = EntityUtil.copy(dbQuit, SeriesOrderTouristQuitNoticeAddQuitItemReq.class);
        noticeAddQuitItemReq.setCnSurname(touristInfo.getCnSurname());
        noticeAddQuitItemReq.setCnName(touristInfo.getCnName());
        noticeAddQuitItemReq.setEnSurname(touristInfo.getEnSurname());
        noticeAddQuitItemReq.setEnName(touristInfo.getEnName());
        noticeAddQuitItemReq.setGender(touristInfo.getGender());
        noticeAddQuitItemReq.setGroupFee(touristInfo.getGroupFee());
        noticeAddQuitItemReq.setTouristTypeName(touristInfo.getTouristTypeName());
        noticeAddQuitItemReq.setCollectionFee(dbQuit.getCollectionFee());
        noticeAddQuitItemReqList.add(noticeAddQuitItemReq);

        SeriesOrderTouristQuitNoticeAddReq noticeAddReq = new SeriesOrderTouristQuitNoticeAddReq();
        noticeAddReq.setCustomerRights(seriesTripScheduleDataDTO.getCustomerRights());
        noticeAddReq.setQuitReason(dbQuit.getQuitReason());
//        noticeAddReq.setCompanyNotes();
        noticeAddReq.setPassengerName(touristInfo.getEnSurname() + " " + touristInfo.getEnName() +
                "(" + touristInfo.getCnSurname() + " " + touristInfo.getCnName() + ")");
//        noticeAddReq.setAgent();
        noticeAddReq.setTourCode(tripScheduleDTO.getTripNumber());
        noticeAddReq.setDays(seriesTripScheduleDataDTO.getTravelDays());
        noticeAddReq.setDepDate(Utils.getDayAndWeek(tripScheduleDTO.getDepartureDate().atStartOfDay()));
        noticeAddReq.setRoute(seriesTripScheduleDataDTO.getTitle());
        noticeAddReq.setEnquiryNo(Utils.getRandom6());
        noticeAddReq.setEnquiryTime(Constants.QUERY_TIME);
        noticeAddReq.setQuitItemList(noticeAddQuitItemReqList);
        noticeAddReq.setPaidInAmount(touristInfo.getTotalPaidIn());
        noticeAddReq.setRefundAmount(dbQuit.getRefundAmount());
        noticeAddReq.setGroupFee(touristInfo.getGroupFee());
        noticeAddReq.setOrderNumber(dbOrder.getOrderNumber());
        noticeAddReq.setReceiptNumber(iSeriesOrderService.getReceiptNumberQuit(currentUser.getId()));
        noticeAddReq.setCollectionFee(dbQuit.getCollectionFee());
        UserDTO userInfo = iSysUserService.queryCacheUser(currentUser.getId());
        if (userInfo != null) {
            if (StringUtils.isNotBlank(userInfo.getCnSurname()) && StringUtils.isNotBlank(userInfo.getCnName())) {
                noticeAddReq.setCreateUser(userInfo.getCnSurname() + userInfo.getCnName());
            }
            noticeAddReq.setDepartmentName(userInfo.getDept());
        }
        SeriesOrderTouristQuitNotice quitNotice = new SeriesOrderTouristQuitNotice();
        quitNotice.setOrderId(dbOrder.getId());
        quitNotice.setScheduleId(dbOrder.getScheduleId());
        quitNotice.setQuitId(dbQuit.getId());
        quitNotice.setTouristName(noticeAddReq.getPassengerName());
        quitNotice.setCustomerRights(noticeAddReq.getCustomerRights());
        quitNotice.setQuitReason(noticeAddReq.getQuitReason());
        quitNotice.setCompanyNotes(noticeAddReq.getCompanyNotes());
        quitNotice.setNotice(JSON.toJSONString(noticeAddReq));
        int insertQuitNotice = seriesOrderTouristQuitNoticeMapper.insert(quitNotice);
        if (insertQuitNotice <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        MainDataCurrencyUpdateStatusReq cnyCurrencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
        cnyCurrencyUpdateStatusReq.setId(CurrencyIdCode.CNY.getCode());
        Result<MainDataCurrencyQueryDTO> cnyCurrencyQueryDTOResult = iMainDataCurrencyService.query(cnyCurrencyUpdateStatusReq);
        if (!cnyCurrencyQueryDTOResult.isSuccess() || cnyCurrencyQueryDTOResult.getData() == null) {
            return Result.failed(SystemError.SYS_411);
        }
        MainDataCurrencyQueryDTO cnyCurrencyQueryDTO = cnyCurrencyQueryDTOResult.getData();

        QueryWrapper<SeriesOrderCollection> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.lambda().eq(SeriesOrderCollection::getOrderId, req.getOrderId());
        queryWrapper3.lambda().eq(SeriesOrderCollection::getTouristId, req.getTouristId());
        queryWrapper3.lambda().and(object -> object.eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.BANK_PREFERENCE.getCode())
//                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.POINTS.getCode())
                .or().eq(SeriesOrderCollection::getCollectionWayId, CollectionRefundWayIdCode.OPERATE_PROMOTION.getCode()));
        queryWrapper3.lambda().eq(SeriesOrderCollection::getIsDeleted, IsDeletedCode.NO.getCode());
        List<SeriesOrderCollection> collectionList = seriesOrderCollectionMapper.selectList(queryWrapper3);

        /*CrmMemberQueryReq crmMemberQueryReq = new CrmMemberQueryReq(QueryType.PHONE.getCode(), dbOrder.getMemberMobile(), null);
        CrmAccountDTO crmAccountDTO = iCrmMemberService.queryAccountDetail(crmMemberQueryReq);
        if(crmAccountDTO == null) {
            throw new BusinessException(SystemError.SYS_411);
        }*/
        for (SeriesOrderCollection collection : collectionList) {
            if (Objects.equals(collection.getCollectionWayId(), CollectionRefundWayIdCode.BANK_PREFERENCE.getCode())) {
                String relationInfoJson = collection.getRelationInfoJson();
                if(StringUtils.isBlank(relationInfoJson)) {
                    throw new BusinessException(SystemError.SYS_411);
                }
                RelationInfoJsonBankPreference relationInfoJsonBankPreference = JSON.parseObject(relationInfoJson, RelationInfoJsonBankPreference.class);
                OperateBankRefundReq operateBankRefundReq = new OperateBankRefundReq();
                operateBankRefundReq.setId(relationInfoJsonBankPreference.getBankPreferenceId());
                operateBankRefundReq.setBusinessType(BusinessTypeCode.GROUP.getCode());
                operateBankRefundReq.setRefundTotalPaidIn(collection.getPaidInAmount());
                operateBankRefundReq.setRelationId(req.getScheduleId());
                operateBankRefundReq.setChannelId(OrderSource.CPM.getCode().longValue());
           //     operateBankRefundReq.setDiscountObjectId(crmAccountDTO.getType().longValue());
                operateBankRefundReq.setDiscountObjectId(3L);
                Result result = iOperateBankPreferenceService.refundUpdate(operateBankRefundReq, currentUser);
                if(!result.isSuccess()) {
                    throw new BusinessException(SeriesOrderErrorCode.QUIT_ERROR);
                }
            } else if(Objects.equals(collection.getCollectionWayId(), CollectionRefundWayIdCode.POINTS.getCode())) {
//                ContactQueryDTO contactQuery = iCrmMemberService.queryMember(crmMemberQueryReq);
//                if (contactQuery == null) {
//                    return Result.failed(SeriesOrderErrorCode.MEMBER_NOT_FOUND_ERROR);
//                }
//
//                MathContext context = new MathContext(2, RoundingMode.HALF_DOWN);
//                //積分=金額（HKD）÷人民幣CRM匯率×100
//                BigDecimal points = (collection.getPaidInAmount().divide(cnyCurrencyQueryDTO.getCrmExchangeRate(), context)).multiply(
//                        new BigDecimal(100));
//                BigDecimal xCtsRmbAmount = collection.getPaidInAmount().divide(cnyCurrencyQueryDTO.getCrmExchangeRate(), 2, BigDecimal.ROUND_HALF_UP);
//                CrmMemberUpdatePointsReq crmMemberUpdatePointsReq = new CrmMemberUpdatePointsReq();
//                crmMemberUpdatePointsReq.setMemberId(dbOrder.getMemberMobile());
//                crmMemberUpdatePointsReq.setUpdateType(PlusTypeCode.PLUS.getCode());
//                crmMemberUpdatePointsReq.setNumPoints(points);//do积分点数
//                crmMemberUpdatePointsReq.setXCtsProdDesc(ProdNameCode.HK_MO_GROUP.getMsg() + "-" + XCtsProdCode.THEME_TOURIST.getMsg() + "(旅行團)");//do板塊產品描述 (建議使用: 集團產品名稱 + “ – “ + 板塊產品名稱, 例如: 港澳参团游 - 主题游)")
//                crmMemberUpdatePointsReq.setTxnNum(dbOrder.getOrderNumber());//do交易編號 (如為旅行團交易, 目前我們的格式是 旅行團交易編號 + ‘-‘ + 序號, 例如: 01P08192131025A155506-1
//                crmMemberUpdatePointsReq.setAmtVal(collection.getPaidInAmount());
//                crmMemberUpdatePointsReq.setXCtsRmbAmount(xCtsRmbAmount);
//                crmMemberUpdatePointsReq.setCreateUserid(String.valueOf(currentUser.getId()).substring(0, 12));
//                crmMemberUpdatePointsReq.setXCtsTxnOrgCode(XCtsTxnOrgCode.HK_MO_MARKET.getCode());
//                crmMemberUpdatePointsReq.setTxnChannelCd(TxnChannelCdCode.STORE.getCode());
//                if (Objects.equals(dbOrder.getOrderType(), OrderTypeCode.CLIENT.getCode())) {
//                    crmMemberUpdatePointsReq.setXCtsTxnChnNum(XCtsTxnChnNumCode.HK_TOURIST_MARKET.getCode());
//                } else if (Objects.equals(dbOrder.getOrderType(), OrderTypeCode.PROXY.getCode())) {
//                    crmMemberUpdatePointsReq.setXCtsTxnChnNum(XCtsTxnChnNumCode.HK_TOURIST_PROXY.getCode());
//                }
//                crmMemberUpdatePointsReq.setProdName(ProdNameCode.HK_MO_GROUP.getCode());
//                crmMemberUpdatePointsReq.setXCtsProdCode(XCtsProdCode.THEME_TOURIST.getCode());
//                iCrmMemberService.updatePoints(crmMemberUpdatePointsReq, contactQuery);
            } else if(Objects.equals(collection.getCollectionWayId(), CollectionRefundWayIdCode.OPERATE_PROMOTION.getCode())) {
                String relationInfoJson = collection.getRelationInfoJson();
                if(StringUtils.isBlank(relationInfoJson)) {
                    throw new BusinessException(SystemError.SYS_411);
                }
                RelationInfoJsonDiscount relationInfoJsonDiscount = JSON.parseObject(relationInfoJson, RelationInfoJsonDiscount.class);
                OperatePromotionRefundReq operatePromotionRefundReq = new OperatePromotionRefundReq();
                operatePromotionRefundReq.setId(relationInfoJsonDiscount.getDiscountId());
                operatePromotionRefundReq.setBusinessType(BusinessTypeCode.GROUP.getCode());
                operatePromotionRefundReq.setTotalPaidIn(collection.getPaidInAmount());
                operatePromotionRefundReq.setRelationId(req.getScheduleId());
                operatePromotionRefundReq.setChannelId(OrderSource.CPM.getCode().longValue());
//                operatePromotionRefundReq.setDiscountObjectId(crmAccountDTO.getType().longValue());
                operatePromotionRefundReq.setDiscountObjectId(3L);
                iOperatePromotionService.refund(operatePromotionRefundReq, currentUser);
            }
        }

//        //更新会员信息
//        dbOrder.setMemberId(crmAccountDTO.getConIntegrationId());
//        dbOrder.setMemberEmail(crmAccountDTO.getConEmailAddr());
//        dbOrder.setMemberMobile(crmAccountDTO.getConCellPhNum());
//        dbOrder.setMemberLevel(String.valueOf(crmAccountDTO.getLevel()));
//        dbOrder.setMemberName(crmAccountDTO.getNameCn());
//        dbOrder.setMemberType(crmAccountDTO.getType());
//
//        if(Objects.equals(crmAccountDTO.getType(), CrmAccountType.STAR.getCode())) {
//            ContactQueryDTO contactQueryDTO = iCrmMemberService.queryMember(crmMemberQueryReq);
//            if(contactQueryDTO == null) {
//                throw new BusinessException(SystemError.SYS_411);
//            }
//            dbOrder.setMemberScore(String.valueOf(contactQueryDTO.getMember().getPoint1Value()));
//        }
//        seriesOrderMapper.updateById(dbOrder);

        if (Objects.equals(touristInfo.getBuyInsurance(), ISCode.YES.getCode())) {
            //退保
            try {
                List<CancelReq> cancelReqList = new ArrayList<>();
                CancelReq cancelReq = new CancelReq();
                cancelReq.setPolicyNo(touristInfo.getInsurancePolicyNo());
                cancelReq.setOperatorCode(PacificUtil.OPERATORCODE);
                cancelReqList.add(cancelReq);
                iInsuranceService.policyCancel(cancelReqList);
            } catch (Exception exception) {
                throw new BusinessException(SeriesOrderErrorCode.REFUND_INSURANCE_ERROR);
            }

            //查找收据 !!!
            SeriesOrderReceiptDetailsGetInsuranceReq receiptDetailsGetInsuranceReq = new SeriesOrderReceiptDetailsGetInsuranceReq();
            receiptDetailsGetInsuranceReq.setOrderId(req.getOrderId());
            receiptDetailsGetInsuranceReq.setTouristId(req.getTouristId());
            SeriesOrderReceiptDetailsGetInsuranceDTO receiptDetailsGetInsuranceDTO = seriesOrderReceiptDetailsMapper.selectGetInsuranceBySelective(
                    receiptDetailsGetInsuranceReq);
            if (receiptDetailsGetInsuranceDTO == null || StringUtils.isBlank(receiptDetailsGetInsuranceDTO.getReceipJson())) {
                throw new BusinessException(SystemError.SYS_500);
            }
            SeriesOrderReceiptDetailsPreviewInsuranceDTO dto = JSON.parseObject(receiptDetailsGetInsuranceDTO.getReceipJson(),
                    SeriesOrderReceiptDetailsPreviewInsuranceDTO.class);
            if (dto == null) {
                throw new BusinessException(SystemError.SYS_500);
            }

            List<SeriesOrderCollectionCollectionInsuranceItemReq> itemList = new ArrayList<>();
            for (SeriesOrderReceiptDetailsPreviewInsuranceItemDTO itemDTO : dto.getInsuredList()) {
                if (Objects.equals(itemDTO.getTouristId(), req.getTouristId())) {
                    continue;
                }
                SeriesOrderCollectionCollectionInsuranceItemReq itemReq = EntityUtil.copy(
                        itemDTO, SeriesOrderCollectionCollectionInsuranceItemReq.class);
                itemList.add(itemReq);
            }

            //作废收据
            SeriesOrderReceiptInvalidReq receiptInvalidReq = new SeriesOrderReceiptInvalidReq();
            receiptInvalidReq.setId(receiptDetailsGetInsuranceDTO.getId());
            iSeriesOrderReceiptDetailsService.invalid(receiptInvalidReq, currentUser);

            //退保险以后，重新购买保险调用接口失败后不需要删除保险的项目，有通知发送给销售即可
            if(itemList.size() > 0) {
//                //重新购保
//                SeriesOrderCollectionCollectionInsuranceReq insuranceReq = new SeriesOrderCollectionCollectionInsuranceReq();
//                insuranceReq.setInsuranceId(touristInfo.getInsuranceId());
//                insuranceReq.setOrderId(req.getOrderId());
//                insuranceReq.setTouristId(itemList.get(0).getTouristId());
//                insuranceReq.setStartDate(dto.getInsuranceStartDate());
//                insuranceReq.setEndDate(dto.getInsuranceEndDate());
//                insuranceReq.setItemList(itemList);
//                Result result = iSeriesOrderCollectionService.collectionInsurance(insuranceReq, currentUser);
//                if (!result.isSuccess()) {
//                    //无法处理的情况，是否购保已设置为否
//                }
            }
        }

        dbQuit.setRefundStatus(5);
        dbQuit.setModifiedId(currentUser.getId());
        boolean update = updateById(dbQuit);
        if (!update){
            throw new BusinessException(SystemError.SYS_408);
        }

        //财务操作退款
        BillOperateRefundReq req1 = new BillOperateRefundReq();
        req1.setBillNumber(dbQuit.getRefundNumber());
        req1.setBusinessType(SystemBusinessType.OUTBOUND_TRAVEL.getCode());
        req1.setUserId(currentUser.getId());
        Result result = financeBillService.operateRefund(req1);
        if (result == null || !result.isSuccess()){
            throw new BusinessException(SystemError.SYS_437);
        }

        return Result.success(quitNotice.getId());
    }

    /**
     * 封装财务退款请求参数
     * @param order
     * @param tripSchedule
     * @param userDTO
     * @param quit
     * @return
     */
    private BillAddRefundReq packBillAddRefundReq(SeriesOrder order, SeriesTripScheduleDTO tripSchedule, UserDTO userDTO, SeriesOrderTouristQuit quit) {
        BillAddRefundReq req1 = new BillAddRefundReq();
        req1.setBillNumber(quit.getRefundNumber());
        req1.setBusinessType(SystemBusinessType.OUTBOUND_TRAVEL.getCode());
        req1.setCollectionAmount(quit.getCurrencyRefundAmount());
        req1.setCurrencyId(quit.getCurrencyTypeId());
        req1.setCurrencyName(quit.getCurrencyType());
        req1.setExchangeRate(quit.getExchangeRate().doubleValue());
        req1.setSaleOrderNumber(order.getOrderNumber());
        req1.setSaleOrderId(order.getId());
        req1.setProductNumber(tripSchedule.getTripNumber());
        req1.setProductName(tripSchedule.getSeriesTripScheduleDataDTO().getTitle());
        List<String> resourceInfo = new ArrayList<>();
        resourceInfo.add(tripSchedule.getSeriesTripScheduleDataDTO().getTitle());
        req1.setResourceInfo(resourceInfo);
        req1.setSaleUserId(quit.getCreateId());
        req1.setSaleDeptId(userDTO.getDeptId());
        req1.setSaleUserName(userDTO.getFullName());
        req1.setRefundTypeId(quit.getRefundTypeId());
        req1.setRefundType(quit.getRefundType());
        AccountJson refundAccountJson = new AccountJson();
        refundAccountJson.setCardNumber(quit.getRefundAccount());
        req1.setRefundAccountJson(refundAccountJson);
        req1.setRefundTime(quit.getGmtCreate());
        req1.setRefundRemark(quit.getRemark());
        req1.setUserId(userDTO.getId());
        req1.setScheduleId(tripSchedule.getId());
        return req1;
    }

    /**
     * 生成退团单号
     * @param userId
     * @return
     */
    public String getQuitNumber(Long userId){
        //退团单号 門市編號+員工編號+年後2位+月日4位+A+時分秒6位+（T）
        String refundNumber = null;
        try {
            UserDTO userDTO = iSysUserService.queryCacheUser(userId);
            refundNumber = userDTO.getDeptCode()+"-"+userDTO.getEmployeeNumber()+"-"+ DateUtil.fmtNum(LocalDate.now())+
                    "-"+ StrConstant.A.getValue()+"-"+DateUtil.fmt(LocalDateTime.now(),"HHmmss")+"-("+StrConstant.T.getValue()+")";
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_417);
        }
        return refundNumber;
    }

    /**
     * 审核
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(SeriesOrderTouristQuitApprovalReq req) {
        QueryWrapper<SeriesOrderTouristQuit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getApprovalId());
        queryWrapper.eq("is_deleted",0);
        SeriesOrderTouristQuit quit = seriesOrderTouristQuitMapper.selectOne(queryWrapper);
        if (quit == null){
            throw new BusinessException(SystemError.TOUR_ORDER_30019);
        }
        quit.setModifiedId(req.getUserId());
        if (Objects.equals(req.getApprovalStatus(),0)){
            //撤回
            quit.setIsDeleted(1);
            boolean update = updateById(quit);
            if (!update){
                throw new BusinessException(SystemError.SYS_437);
            }
            return Result.success(quit.getId());
        }
        quit.setRefundStatus(req.getApprovalStatus());
        if (Objects.equals(req.getApprovalStatus(),4)){
            //审批拒绝
            boolean update = updateById(quit);
            if (!update){
                throw new BusinessException(SystemError.SYS_437);
            }
            return Result.success(quit.getId());
        }else if (Objects.equals(req.getApprovalStatus(),3)){
            if (req.getCollectionFee() == null || req.getGroupFee() == null){
                throw new BusinessException(SystemError.SYS_402);
            }
            //审批通过
            quit.setCollectionFee(req.getCollectionFee());
            quit.setDeductionGroupFee(req.getGroupFee());
            BigDecimal deductionAmount = quit.getPaidInAmount().subtract(req.getCollectionFee()).subtract(req.getGroupFee());
            quit.setDeductionAmount(deductionAmount);
            BigDecimal subtract = quit.getRefundAmount().subtract(quit.getDeductionAmount());
            if (subtract.compareTo(BigDecimal.ZERO) < 0){
                subtract = BigDecimal.ZERO;
            }
            quit.setRefundAmount(subtract);
            boolean update = updateById(quit);
            if (!update){
                throw new BusinessException(SystemError.SYS_437);
            }
            //新增退款认款请求参数
            UserDTO userDTO = iSysUserService.queryCacheUser(req.getUserId());
            SeriesOrder order = seriesOrderMapper.selectById(quit.getOrderId());
            //修改团总人数
            order.setTotalPeople(order.getTotalPeople()-1);
            SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(order.getScheduleId());
            //更新团期人数
            UpdateScheduleNumReq updateScheduleNumReq = new UpdateScheduleNumReq();
            updateScheduleNumReq.setId(order.getScheduleId());
            updateScheduleNumReq.setNum(1);
            Result updateNumResult = iSeriesTripScheduleService.updateScheduleNum(updateScheduleNumReq);
            if (!updateNumResult.isSuccess()){
                throw new BusinessException(SystemError.SYS_408);
            }
            //已解锁
            order.setIsUnlock(1);
            int updateOrder = seriesOrderMapper.updateById(order);
            if (updateOrder <= 0){
                throw new BusinessException(SystemError.SYS_408);
            }
            List<BillAddRefundReq> reqList = new ArrayList<>();
            BillAddRefundReq req1 = packBillAddRefundReq(order,tripScheduleDTO,userDTO,quit);
            reqList.add(req1);
            //批量新增财务退款记录
            Result result = financeBillService.addRefund(reqList);
            if (result == null || !result.isSuccess()){
                throw new BusinessException(SystemError.SYS_437);
            }
        }
        Result<ApprovalCheckDTO> result = iSysApprovalService.check(req.getApprovalId(), req.getUserId(),
                req.getApprovalStatus(), req.getComments());
        if (!result.isSuccess()) {
            return Result.failed(SystemError.SYS_500);
        }
        return Result.success(quit.getId());
    }

    /**
     * 审批中心-退团信息
     *
     * @param req
     * @return
     */
    @Override
    public Result<ApprovalQuitInfoDTO> approvalQuitInfo(ApprovalIdReq req) {
        QueryWrapper<SeriesOrderTouristQuit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("approval_id",req.getApprovalId());
        queryWrapper.eq("is_deleted",0);
        SeriesOrderTouristQuit quit = seriesOrderTouristQuitMapper.selectOne(queryWrapper);
        if (quit == null){
            throw new BusinessException(SystemError.SYS_411);
        }
        ApprovalQuitInfoDTO dto = EntityUtil.copy(quit,ApprovalQuitInfoDTO.class);
        return Result.success(dto);
    }
}
